﻿using System.Collections.Generic;
using log4net.Appender;
using log4net.Util;

namespace Sail.Logging
{
    public class SailFileAppender : RollingFileAppender
    {
        /// <summary>
        /// 以为已经存在的日志文件名后缀的的结合
        /// </summary>
        private static readonly Dictionary<string, int> _suffixes = new Dictionary<string, int>();

        /// <summary>
        /// 尝试调用OpenFile方法的次数
        /// </summary>
        private const int Retries = 50;

        /// <summary>
        /// 后缀字典集合在内存中的最大个数，大于这个数进行回收
        /// </summary>
        private const int MaxSuffixes = 100;

        /// <summary>
        ///
        /// </summary>
        /// <param name="fileName">配置文件指定的文件名</param>
        /// <param name="append">是否添加到已存在的日志文件中</param>
        protected override void OpenFile(string fileName, bool append)
        {
            lock (this)
            {
                bool fileOpened = false;
                string completeFilename = GetNextOutputFileName(fileName);
                string currentFilename = fileName;

                if (_suffixes.Count > MaxSuffixes)
                {
                    _suffixes.Clear();
                }

                if (!_suffixes.ContainsKey(completeFilename))
                {
                    _suffixes[completeFilename] = 0;
                }

                int newSuffix = _suffixes[completeFilename];

                for (int i = 1; !fileOpened && i <= Retries; i++)
                {
                    try
                    {
                        if (newSuffix > 0)
                        {
                            currentFilename = string.Format("{0}-{1}", fileName, newSuffix);
                        }

                        BaseOpenFile(currentFilename, append);

                        fileOpened = true;
                    }
                    catch
                    {
                        newSuffix = _suffixes[completeFilename] + i;

                        LogLog.Error(string.Format("SailFileAppender: 打开[{0}]失败. 试图用 [{1}-{2}] 替代.", fileName, fileName,
                                                   newSuffix));
                    }
                }

                _suffixes[completeFilename] = newSuffix;
            }
        }

        /// <summary>
        /// 调用基类得OpenFile方法
        /// </summary>
        /// <param name="fileName">配置文件指定的文件名</param>
        /// <param name="append">是否添加到已存在的日志文件中</param>
        protected virtual void BaseOpenFile(string fileName, bool append)
        {
            base.OpenFile(fileName, append);
        }
    }
}